package com.codecrecord;

import android.graphics.SurfaceTexture;
import android.opengl.EGL14;
import android.util.Log;

import java.io.File;

/**
 * Created by fuyao on 2017/8/6.
 */

public class GrafikaRecord extends AbsRecord {
    private static final String TAG = "fuyao-GrafikaRecord";

    private static final int RECORDING_OFF = 0;
    private static final int RECORDING_ON = 1;
    private static final int RECORDING_RESUMED = 2;
    private static final int RECORDING_OFF_PENDDING = 3;

    private static TextureMovieEncoder sVideoEncoder = new TextureMovieEncoder();

    private SurfaceTexture mSurfaceTexture;
    private boolean mRecordingEnabled;
    private int mRecordingStatus;

    private String mVideoPath;
    private boolean mRecordVoice;
    private TextureMovieEncoder.OnVideoDone mOnVideoDone;
    private int mTextureId;
    private boolean mTextureIdSet = false;

    public GrafikaRecord() {
        Log.d(TAG, "GrafikaRecord");
        mRecordingStatus = RECORDING_OFF;
        mRecordingEnabled = false;
    }

    @Override
    public boolean init() {
        Log.d(TAG, "init");
        if(sVideoEncoder.isRecording()) {
            return false;
        }
        return true;
        // We're starting up or coming back.  Either way we've got a new EGLContext that will
        // need to be shared with the video encoder, so figure out if a recording is already
        // in progress.

        //TODO: now not need resume,so do nothing here
//        mRecordingEnabled = sVideoEncoder.isRecording();
//        if (mRecordingEnabled) {
//            mRecordingStatus = RECORDING_RESUMED;
//        } else {
//            mRecordingStatus = RECORDING_OFF;
//        }

    }

    @Override
    public void setVideoPath(String videoPath) {
        this.mVideoPath = videoPath;
    }

    @Override
    public void setRecordVoice(boolean recordVoice) {
        mRecordVoice = recordVoice;
    }

    @Override
    public void release() {
    }

    @Override
    public void setTexture(int texId, SurfaceTexture surfaceTexture) {
        mSurfaceTexture = surfaceTexture;
        mTextureId = texId;
        mTextureIdSet = false;
    }

    @Override
    public void setTextureSize(int width, int height) {

    }

    @Override
    public void newFrame() {
// Log.d(TAG, "onDrawFrame tex=");

        // If the recording state is changing, take care of it here.  Ideally we wouldn't
        // be doing all this in onDrawFrame(), but the EGLContext sharing with GLSurfaceView
        // makes it hard to do elsewhere.
        if (mRecordingEnabled) {
            switch (mRecordingStatus) {
                case RECORDING_OFF:
                    Log.d(TAG, "START recording");
                    Log.d(TAG, "save path is " + mVideoPath);
                    sVideoEncoder.startRecording(new TextureMovieEncoder.EncoderConfig(
                            new File(mVideoPath), 1920, 1080,
                            calcBitRate(0.50f, 15, 1920, 1080),
                            EGL14.eglGetCurrentContext(), mRecordVoice, mOnVideoDone));
                    mRecordingStatus = RECORDING_ON;
                    break;
                case RECORDING_RESUMED:
                    Log.d(TAG, "RESUME recording");
                    sVideoEncoder.updateSharedContext(EGL14.eglGetCurrentContext());
                    mRecordingStatus = RECORDING_ON;
                    break;
                case RECORDING_ON:
                    // yay
                    break;
                case RECORDING_OFF_PENDDING:
                    if(!sVideoEncoder.isRecording()){
                        Log.d(TAG, "Really STOP");
                        mRecordingStatus = RECORDING_OFF;
                    }
                    return;
                default:
                    throw new RuntimeException("unknown status " + mRecordingStatus);
            }
        } else {
            switch (mRecordingStatus) {
                case RECORDING_ON:
                case RECORDING_RESUMED:
                    // stop recording
                    Log.d(TAG, "notify STOP recording");
                    sVideoEncoder.stopRecording();
                    mRecordingStatus = RECORDING_OFF_PENDDING;
                    return;
                case RECORDING_OFF_PENDDING:
                    if(!sVideoEncoder.isRecording()){
                        Log.d(TAG, "Really STOP");
                        mRecordingStatus = RECORDING_OFF;
                    }
                    return;
                case RECORDING_OFF:
                    // yay
                    return;
                default:
                    throw new RuntimeException("unknown status " + mRecordingStatus);
            }
        }

        //If reach here, mRecordingStatus must be true
        if (!mTextureIdSet) {
            mTextureIdSet = true;
            sVideoEncoder.setTextureId(mTextureId);
        }
        if (null != mSurfaceTexture) {
            mSurfaceTexture.updateTexImage();
        }
        // Tell the video encoder thread that a new frame is available.
        // This will be ignored if we're not actually recording.
        sVideoEncoder.frameAvailable(mSurfaceTexture);
    }

    @Override
    public boolean isRecording() {
        return sVideoEncoder.isRecording();
    }

    @Override
    public int handleStartRecording(TextureMovieEncoder.OnVideoDone onVideoDone) {
        if (sVideoEncoder.isRecording()){
            return -1;
        }
        Log.d(TAG, "changeRecordingState: was " + mRecordingEnabled + " now " + true);
        mRecordingEnabled = true;
        mOnVideoDone = onVideoDone;
        return 0;
    }

    @Override
    public void handleStopRecording() {
        Log.d(TAG, "changeRecordingState: was " + mRecordingEnabled + " now " + false);
        mRecordingEnabled = false;
    }

    @Override
    public void setOnVideoDone(TextureMovieEncoder.OnVideoDone onVideoDone) {
        mOnVideoDone = onVideoDone;
    }

    private int calcBitRate(float bpp, int frameRate, int width, int height) {
        final int bitrate = (int) (bpp * frameRate * width * height);
        Log.i(TAG, String.format("bitrate=%5.2f[Mbps]", bitrate / 1024f / 1024f));
        return 500000;
//        return bitrate;
    }
}
